package com.ds.dsfans.shell.util.common;


import com.ds.dsfans.shell.util.adb.device.Node;
import com.ds.dsfans.shell.util.common.fc.FindFunction;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class XmlUtil extends DefaultHandler {

    // 所以node节点
    private NodeList nodeList;
    private List<Element> elements;
    private DocumentBuilderFactory bbf;
    private DocumentBuilder builder;
    private Document doc;
    private String deviceCode;


    public XmlUtil(String path, String deviceCode) {
        this.deviceCode = deviceCode;
        bbf = DocumentBuilderFactory.newInstance();
        try {
            builder = bbf.newDocumentBuilder();
            reset(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * @Description:
     * 防止临时文件被清空
     * @Author zhangRenHuo
     * @Date 17:48 2020/8/6
     * @return
     **/
    public void reset(String path) {
        try {
            doc = builder.parse(new File(path));
        } catch (Exception e) {
            System.err.println("文件不存在---");
            doc = builder.newDocument();
//            e.printStackTrace();
        }
        Element root = doc.getDocumentElement();
        if (null != root) {
            nodeList = root.getElementsByTagName("node");
        }
        init();
    }

    // 初始化
    private void init() {
        elements = new ArrayList<>();
        if (null != nodeList) {
            for (int i = 0; i < nodeList.getLength(); i++) {
                elements.add((Element) nodeList.item(i));
            }
        }
    }

    /*
     * @Description:
     * 根据id查询
     * @Author zhangRenHuo
     * @Date 16:05 2020/8/5
     * @return
     **/
    public XmlUtil findById(String id) {
        return find(item -> id.equals(item.getAttribute("resource-id")));
    }

    public XmlUtil findByParentAndId(String id) {
        return find(item -> {
            Element parentNode = (Element) item.getParentNode();
            String attribute = parentNode.getAttribute("resource-id");
            return attribute.equals(id);
        });
    }

    /**
     * 查询子集id符合的
     */
    public XmlUtil findByChildAndId(String id) {
        return find(item -> {
            NodeList childNodes = item.getChildNodes();
            for (int i = 0; i < childNodes.getLength(); i++) {
                Element el = (Element) childNodes.item(i);
                if (el.getAttribute("resource-id").equals(id)) {
                    return true;
                }
            }
            return false;
        });
    }

    /*
     * @Description:
     * 根据class查询
     * @Author zhangRenHuo
     * @Date 16:07 2020/8/5
     * @return
     **/
    public XmlUtil findByClassName(String className) {
        elements = elements.stream().filter(item -> item.getAttribute("class").equals(className)).collect(Collectors.toList());
        return this;
    }

    public XmlUtil findByParentAndClassName(String className) {
        return find(item -> {
            Element parentNode = (Element) item.getParentNode();
            String attribute = parentNode.getAttribute("class");
            return attribute.equals(className);
        });
    }

    /**
     * 根据子节点的class查询
     *
     * @param className
     * @return
     */
    public XmlUtil findByChildAndClassName(String className) {
        return find(item -> {
            NodeList childNodes = item.getChildNodes();
            for (int i = 0; i < childNodes.getLength(); i++) {
                Element el = (Element) childNodes.item(i);
                if (el.getAttribute("class").equals(className)) {
                    return true;
                }
            }
            return false;
        });
    }

    /*
     * @Description:
     * 根据文本查询 支持正则
     * @Author zhangRenHuo
     * @Date 16:41 2020/8/5
     * @return
     **/
    public XmlUtil findByText(String text) {
        return find(item -> {
            String attribute = item.getAttribute("text");
            return attribute.equals(text) || Pattern.matches(text, attribute);
        });
    }

    public XmlUtil findByParentAndText(String text) {
        return find(item -> {
            Element parentNode = (Element) item.getParentNode();
            String attribute = parentNode.getAttribute("text");
            return attribute.equals(text) || Pattern.matches(text, attribute);
        });
    }


    public XmlUtil findByChildAndText(String text) {
        return find((item) -> {
            NodeList childNodes = item.getChildNodes();
            for (int i = 0; i < childNodes.getLength(); i++) {
                Element el = (Element) childNodes.item(i);
                String attribute = el.getAttribute("text");
                if (attribute.equals(text) || Pattern.matches(text, attribute)) {
                    return true;
                }
            }
            return false;
        });
    }

    public XmlUtil find(FindFunction<Element, Boolean> fuction) {
        elements = elements.stream().filter(item ->
                fuction.start(item)
        ).collect(Collectors.toList());
        return this;
    }

    /*
     * @Description:
     * 根据描述查询 支持正则
     * @Author zhangRenHuo
     * @Date 16:42 2020/8/5
     * @return
     **/
    public XmlUtil findByDesc(String desc) {
        elements = elements.stream().filter(item -> {
            String attribute = item.getAttribute("content-desc");
            return attribute.equals(desc) || Pattern.matches(desc, attribute);
        }).collect(Collectors.toList());
        return this;
    }

    public XmlUtil findByParentAndDesc(String desc) {
        elements = elements.stream().filter(item -> {
            Element parentNode = (Element) item.getParentNode();
            String attribute = parentNode.getAttribute("content-desc");
            return attribute.equals(desc) || Pattern.matches(desc, attribute);
        }).collect(Collectors.toList());
        return this;
    }

    public XmlUtil findByChildAndDesc(String desc) {
        elements = elements.stream().filter(item -> {
            NodeList childNodes = item.getChildNodes();
            for (int i = 0; i < childNodes.getLength(); i++) {
                Element el = (Element) childNodes.item(i);
                String attribute = el.getAttribute("content-desc");
                if (attribute.equals(desc) || Pattern.matches(desc, attribute)) {
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());
        return this;
    }

    public XmlUtil findByChildNum(Integer num) {
        elements = elements.stream().filter(item -> {
            NodeList childNodes = item.getChildNodes();
            return childNodes.getLength() == num;
        }).collect(Collectors.toList());
        return this;
    }

    /*
     * @Description:
     * 得到子集
     * @Author zhangRenHuo
     * @Date 17:25 2020/8/6
     * @return
     **/
    public XmlUtil getChild() {
        elements = elements.stream().map(item -> {
            ArrayList<Element> elements = new ArrayList<>();
            NodeList childNodes = item.getChildNodes();
            for (int i = 0; i < childNodes.getLength(); i++) {
                Element element = (Element) childNodes.item(i);
                elements.add(element);
            }
            return elements;
        }).flatMap(item -> item.stream()).collect(Collectors.toList());
        return this;
    }

    /*
     * @Description:
     * 获取元素节点
     * @Author zhangRenHuo
     * @Date 16:05 2020/8/5
     * @return
     **/
    public List<Node> getNodes() {
        ArrayList<Node> nodes = new ArrayList<>();
        elements.stream().forEach(item -> {
            Node node = new Node();
            node.setDeviceCode(deviceCode);
            node.setText(item.getAttribute("text"));
            node.setResourceId(item.getAttribute("resource-id"));
            node.setClassName(item.getAttribute("class"));
            node.setContentDesc(item.getAttribute("content-desc"));
            node.setCheckable(item.getAttribute("checkable"));
            node.setChecked(item.getAttribute("checked"));
            node.setClickable(item.getAttribute("clickable"));
            node.setBounds(item.getAttribute("bounds"));
            // 将节点的xy坐标储存用于点击
            centerXY(node, item.getAttribute("bounds"));
            nodes.add(node);
        });
        return nodes;
    }

    private void centerXY(Node node, String bounds) {
        Pattern p = Pattern.compile("\\d{1,4}");
        Matcher matcher = p.matcher(bounds);
        ArrayList<Integer> list = new ArrayList<>();
        while (matcher.find()) {
            list.add(Integer.parseInt(matcher.group(0)));
        }
        if (list.size() == 4) {
            node.setCenterX((list.get(0) + list.get(2)) / 2);
            node.setCenterY((list.get(1) + list.get(3)) / 2);
        }
    }

    public List<Element> getElements() {
        return elements;
    }

}
